package com.recharge.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.recharge.common.domain.PageDO;
import com.recharge.common.enums.ErrorCode;
import com.recharge.common.result.ResultDO;
import com.recharge.common.result.ResultSupport;
import com.recharge.common.util.*;
import com.recharge.common.util.http.HttpUtil;
import com.recharge.core.entity.*;
import com.recharge.core.mapper.MerchantCallbakMapper;
import com.recharge.core.mapper.MerchantMapper;
import com.recharge.core.mapper.OrderMapper;
import com.recharge.domain.query.MerchantQueryDO;
import com.recharge.domain.vo.*;
import com.recharge.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author reagan
 * @since 2020-08-19
 */
@Service
public class MerchantServiceImpl extends ServiceImpl<MerchantMapper, MerchantEntity> implements MerchantService {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    private final int CALLBACK_SEND_NUMBER = 50;

    @Value("${user.reset-password}")
    private String userPassword;

    @Value("${application.contextPath}")
    private String contextPath;

    @Value("${server.host-ip}")
    private String hostIp;

    @Autowired
    private MerchantAccountService merchantAccountService;

    @Autowired
    private DepositService depositService;

    @Autowired
    private MerchantCallbakMapper merchantCallbakMapper;

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private RouteFilterService routeFilterService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private GoodsMerchantService goodsMerchantService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    private ExecutorService executorService = null;

    @Value("${node.name}")
    private Integer nodeName;

    @PostConstruct
    public void init() {

        executorService =  new ThreadPoolExecutor(10, 100,
                5,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(512),
                new ThreadPoolExecutor.DiscardPolicy());
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO add(MerchantDO domain) {

        MerchantEntity entity = new MerchantEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        Integer count = -1;
        try {
            count = baseMapper.selectCount(Wrappers.<MerchantEntity>lambdaQuery().eq(MerchantEntity::getMerchantName, entity.getMerchantName()).eq(MerchantEntity::getIsDelete, Constant.IS_DELETE_FALSE));
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }
        if(count != null && count >= 1){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PROVIDER_ADD_MERCHANT_NAME_EXIST_ERROR);
            logger.debug("error code：" + ErrorCode.PROVIDER_ADD_MERCHANT_NAME_EXIST_ERROR.getCode() + " msg" + ErrorCode.PROVIDER_ADD_MERCHANT_NAME_EXIST_ERROR.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        entity.setMerchantNo(SnowflakeIdWorker.getId());
        entity.setCreateDate(Calendar.getInstance().getTime());
        entity.setModifiDate(entity.getCreateDate());
        entity.setModifier(entity.getCreator());
        entity.setPrivateKey(DESUtil.encrypt(entity.getPassword(), entity.getMerchantNo() + "-" + entity.getPassword()));

        if(entity != null && domain != null && domain.getWarnAmountt() != null){
            entity.setWarnAmountt(domain.getWarnAmountt() * 1000);
        }

        boolean res = false;

        try {
            res = this.save(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.MERCHANT_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.MERCHANT_ADD_ERROR.getCode() + " msg" + ErrorCode.MERCHANT_ADD_ERROR.getMsg());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return result;
        }

        result = merchantAccountService.add(entity.getId());
        if(!result.isSuccess()) {
            try {
                throw new Exception(result.getErrorCode().getMsg());
            } catch (Exception e) {
                logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return result;
            }
        }
        //新增用户
        UserDetailDO domainUserDetail = new UserDetailDO();
        domainUserDetail.setType(2);
        domainUserDetail.setRealName(domain.getMerchantName());

        UserLoginDO domainUser = new UserLoginDO();
        domainUser.setMerchantId(entity.getId());
        domainUser.setUsername(domain.getUsername());
        domainUser.setPassword(userPassword);
        domainUser.setUserDetailDO(domainUserDetail);
        result = userService.add(domainUser);
        if(!result.isSuccess()) {
            try {
                throw new Exception(result.getErrorCode().getMsg());
            } catch (Exception e) {
                logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return result;
            }
        }

        domain = getDomain(entity);
        redisUtil.set(Constant.MERCHANT_INFO + ":" + entity.getMerchantNo(), domain);
        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO edit(MerchantDO domain) {

        MerchantEntity entity = new MerchantEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        entity.setModifiDate(Calendar.getInstance().getTime());

        Integer count = -1;
        try {
            count = baseMapper.selectCount(Wrappers.<MerchantEntity>lambdaQuery().eq(MerchantEntity::getMerchantName, entity.getMerchantName()).ne(MerchantEntity::getId, entity.getId()).eq(MerchantEntity::getIsDelete, Constant.IS_DELETE_FALSE));
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        if(count != null && count >= 1){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PROVIDER_ADD_MERCHANT_NAME_EXIST_ERROR);
            logger.debug("error code：" + ErrorCode.PROVIDER_ADD_MERCHANT_NAME_EXIST_ERROR.getCode() + " msg" + ErrorCode.PROVIDER_ADD_MERCHANT_NAME_EXIST_ERROR.getMsg());
            return result;
        }
        if(entity != null && domain != null && domain.getWarnAmountt() != null){
            entity.setWarnAmountt(domain.getWarnAmountt() * 1000);
        }


        boolean res = false;
        try {
            res = this.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.MERCHANT_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.MERCHANT_EDIT_ERROR.getCode() + " msg" + ErrorCode.MERCHANT_EDIT_ERROR.getMsg());
            return result;
        }

        try {
            entity = this.getById(domain.getId());
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        domain = getDomain(entity);
        redisUtil.set(Constant.MERCHANT_INFO + ":" + entity.getMerchantNo(), domain);
        return result;
    }

    
    public ResultDO get(String id) {

        ResultDO result = new ResultSupport();
        MerchantEntity entity = null;

        try {
//            entity = this.getById(id);
            entity = merchantMapper.getById(id);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        MerchantDO domain = getDomain(entity);

        if(domain != null && entity != null && entity.getWarnAmountt() != null){
            domain.setWarnAmountt(entity.getWarnAmountt() / 1000);
        }

        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);

        return result;
    }

    public ResultDO getByMerchantNO(String merchantNo) {

        ResultDO result = new ResultSupport();

        MerchantEntity entity = null;

        try {
            entity = this.getOne(Wrappers.<MerchantEntity>lambdaQuery().eq(MerchantEntity::getMerchantNo, merchantNo).eq(MerchantEntity::getStatus, 1).eq(MerchantEntity::getIsDelete, Constant.IS_DELETE_FALSE));
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        MerchantDO domain = getDomain(entity);

        if(domain == null) {
            result.setSuccess(false);
            return result;
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);
        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO remove(String id, String modifier) {

        ResultDO result = merchantAccountService.remove(id, modifier);
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        result = depositService.removeByMerchantId(id);
        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        MerchantEntity entity = new MerchantEntity();

        entity.setModifiDate(Calendar.getInstance().getTime());
        entity.setModifier(modifier);
        entity.setId(id);
        entity.setIsDelete(Constant.IS_DELETE);
        boolean res = false;
        try {
            res = this.updateById(entity);
            //TODO 删除redis中的商户信息
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.MERCHANT_DELETE_ERROR);
            logger.debug("error code：" + ErrorCode.MERCHANT_DELETE_ERROR.getCode() + " msg" + ErrorCode.MERCHANT_DELETE_ERROR.getMsg());
            return result;
        }
        result = get(id);
        MerchantDO merchantDO = (MerchantDO) result.getModel(ResultDO.FIRST_MODEL_KEY);
        redisUtil.del(Constant.MERCHANT_INFO + ":" + merchantDO.getMerchantNo());
        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
	@Override
	public ResultDO resetSecretKey(String id, String username) {
		
		 ResultDO result = new ResultSupport();
		 
		 MerchantEntity merchantEntity =  this.getById(id);

        MerchantEntity entity = new MerchantEntity();

        entity.setModifiDate(Calendar.getInstance().getTime());
        entity.setModifier(username);
        String password = SnowflakeIdWorker.getId();
        entity.setPrivateKey(DESUtil.encrypt(password, merchantEntity.getMerchantNo() + "-" + password));
        entity.setPassword(password);
        entity.setId(id);

        boolean res = false;
        try {
            res = this.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.API_MERCHANT_KEY_RESET);
            logger.debug("error code：" + ErrorCode.API_MERCHANT_KEY_RESET.getCode() + " msg" + ErrorCode.API_MERCHANT_KEY_RESET.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.API_MERCHANT_KEY_RESET);
            logger.debug("error code：" + ErrorCode.API_MERCHANT_KEY_RESET.getCode() + " msg" + ErrorCode.API_MERCHANT_KEY_RESET.getMsg());
            return result;
        }

        return result;
	}

    public ResultDO find(MerchantQueryDO query) {

        ResultDO result = new ResultSupport();

        Page<MerchantEntity> page = new Page<>(query.getCurrentPage(),query.getPageSize());

        IPage<MerchantEntity> iPage = null;

        QueryWrapper<MerchantEntity> queryWrapper = new QueryWrapper<MerchantEntity>();
        if(StringUtils.isNotEmpty(query.getMerchantNo())) {
            queryWrapper.lambda().eq(MerchantEntity::getMerchantNo, query.getMerchantNo());
        }
        if(StringUtils.isNotEmpty(query.getTelephone())) {
            queryWrapper.lambda().eq(MerchantEntity::getTelephone, query.getTelephone());
        }
        if(StringUtils.isNotEmpty(query.getMerchantName())) {
            queryWrapper.lambda().like(MerchantEntity::getMerchantName, query.getMerchantName());
        }
        //有效的
        queryWrapper.lambda().eq(MerchantEntity::getIsDelete, Constant.IS_DELETE_FALSE);
        try {
            iPage = baseMapper.selectPage(page, queryWrapper);
        } catch(Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<MerchantDO> doList = getDomainList(iPage.getRecords());

        if(doList != null && doList.size() >0){
            doList.stream().forEach( item -> {
                if(item != null && item.getWarnAmountt() != null){
                    item.setWarnAmountt(item.getWarnAmountt() / 1000);
                }
            });
        }

        PageDO<MerchantDO> pageDO = new PageDO<>();

        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;

    }

    @Override
    public ResultDO findListInfo(MerchantQueryDO domain) {
        MerchantEntity entity = new MerchantEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("对象转换异常");
            return result;
        }


        Page<MerchantEntity> page = new Page<>(domain.getCurrentPage(),domain.getPageSize());

        IPage<MerchantEntity> iPage = null;

        try {
            iPage = baseMapper.selectInfoPage(page, entity);
        } catch(Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<MerchantEntity> doList = iPage.getRecords();

        if(doList != null && doList.size() >0){
            doList.stream().forEach( item -> {
                if(item != null && item.getWarnAmountt() != null){
                    item.setWarnAmountt(item.getWarnAmountt() / 1000);
                }
            });
        }

        PageDO<MerchantEntity> pageDO = new PageDO<>();

        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;
    }



    public void sendCallBack() {

        while(!Thread.currentThread().interrupted()) {

            List<MerchantCallbakEntity> list = null;
            Page<MerchantCallbakEntity> page = new Page<>(0, CALLBACK_SEND_NUMBER);
            IPage<MerchantCallbakEntity> iPage = null;
            try {
                iPage = merchantCallbakMapper.selectPage(page, Wrappers.<MerchantCallbakEntity>lambdaQuery()
                        .eq(MerchantCallbakEntity::getStatus, Constant.MERCHANT_CALL_STATUS_0)
                        .eq(MerchantCallbakEntity::getNodeName, nodeName)
                        .orderByAsc(MerchantCallbakEntity::getCreateDate));
            } catch (Exception e) {
                e.printStackTrace();
            }

            for (MerchantCallbakEntity entity : iPage.getRecords()) {
                entity.setStatus(Constant.MERCHANT_CALL_STATUS_2);
                int res = -1;
                try {
                    res = merchantCallbakMapper.deleteById(entity.getId());
                } catch (Exception e) {
                    e.printStackTrace();
                    continue;
                }
                executorService.execute(new CallbackThread(entity));
                entity = null;
            }
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    class CallbackThread implements Runnable {

        private MerchantCallbakEntity entity;

        public CallbackThread(MerchantCallbakEntity entity) {
            this.entity = entity;
        }

        public void run() {
            logger.debug("callback Thread :" + entity);
            MerchantCallbakDO domain = new MerchantCallbakDO();
            domain.setSerialNumber(entity.getSerialNumber());
            domain.setOrderNo(entity.getOrderNo());
            domain.setRechargeNumber(entity.getRechargeNumber());
            domain.setCode(entity.getCode());
            domain.setVoucherNo(entity.getVoucherNo());
            int res = -1;
            Gson gson = new Gson();
            String jsonData = gson.toJson(domain);
            String responseData = null;
            try {
                responseData = HttpUtil.post(entity.getCallbackUrl(), jsonData, conn -> {
                            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
                            conn.setRequestProperty("accept", "application/json;charset=utf-8");
                        }
                );
            } catch (Exception e) {
                e.printStackTrace();
            }
            logger.warn("发送异步回调 " + jsonData + " 回调下游接口返回结果为：" + responseData);
            responseData = responseData == null ? "" : responseData;

            int status = 0;

            if (!("ok".equals(responseData.trim()))) {
                entity.setCount(entity.getCount() + 1);
            } else {
                status = Constant.MERCHANT_CALL_STATUS_1;
            }
            if (entity.getCount() >= 5) {
                status = Constant.MERCHANT_CALL_STATUS_fail;
            }

            MerchantCallbakEntity updateEntity = new MerchantCallbakEntity();
            updateEntity.setCount(entity.getCount());
            updateEntity.setId(entity.getId());
            updateEntity.setStatus(status);

            ResultDO result = orderService.getByMerchantSerialNumber(entity.getSerialNumber());
            OrderDO order = null;
            if (result.isSuccess()) {
                order = (OrderDO) result.getModel(ResultDO.FIRST_MODEL_KEY);

                order.setMerchantCallbackInfo(responseData);
                order.setMerchantCallbackStatus(status);
                orderService.saveUpdate(order);
            }

            /*try {
                res = merchantCallbakMapper.updateById(updateEntity);
            } catch (Exception e) {
                e.printStackTrace();
            }*/

        }
    }

    /*public ResultDO callback(String serialNumber, String orderNo, String rechargeNumber, String voucherNo,  Integer code, String message, String url) {

        ResultDO result = new ResultSupport();
        //交易提交失败，订单失败调用会掉
        //加入提交订单到队列中去,订单处理失败
        MerchantCallbakEntity entity = new MerchantCallbakEntity();
        entity.setOrderNo(orderNo);
        entity.setSerialNumber(serialNumber);
        entity.setRechargeNumber(rechargeNumber);
        entity.setVoucherNo(voucherNo);
        entity.setStatus(Constant.MERCHANT_CALL_STATUS_0);
        entity.setCode(code);
        entity.setMessage(message);
        entity.setCallbackUrl(url);
        entity.setNodeName(nodeName);
        entity.setCreateDate(Calendar.getInstance().getTime());
        int res = -1;

        try {
            res = merchantCallbakMapper.insert(entity);
        } catch (Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        if(res <= 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.CALLBACK_MERCHANT_ERROR);
            logger.debug("error code：" + ErrorCode.CALLBACK_MERCHANT_ERROR.getCode() + " msg" + ErrorCode.CALLBACK_MERCHANT_ERROR.getMsg());
            return result;
        }

        sendCallback(entity);

        return result;
    }*/

    public ResultDO callback(String serialNumber, String orderNo, String rechargeNumber, String voucherNo,  Integer code, String message, String url) {
        logger.debug("写下游回调消息：" + serialNumber + ":" + orderNo + ":" + rechargeNumber + ":" + voucherNo);
        int restCount = 0;
        int status = Constant.MERCHANT_CALL_STATUS_fail;
        String responseData = null;
        boolean is = true;

        MerchantCallbakEntity entity = new MerchantCallbakEntity();
        entity.setOrderNo(orderNo);
        entity.setSerialNumber(serialNumber);
        entity.setRechargeNumber(rechargeNumber);
        entity.setVoucherNo(voucherNo);
        entity.setStatus(Constant.MERCHANT_CALL_STATUS_0);
        entity.setCode(code);
        entity.setMessage(message);
        entity.setCallbackUrl(url);
        entity.setNodeName(nodeName);
        entity.setCreateDate(Calendar.getInstance().getTime());

        MerchantCallbakDO domain = new MerchantCallbakDO();
        domain.setSerialNumber(entity.getSerialNumber());
        domain.setOrderNo(entity.getOrderNo());
        domain.setRechargeNumber(entity.getRechargeNumber());
        domain.setCode(entity.getCode());
        domain.setVoucherNo(entity.getVoucherNo());

        do {
            Gson gson = new Gson();
            String jsonData = gson.toJson(domain);
            logger.debug("发送代理商回调:" + entity.getCallbackUrl() + ":" + jsonData +":第"+ restCount +"次");
            try {
                responseData = HttpUtil.post(entity.getCallbackUrl(), jsonData, conn -> {
                            conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
                            conn.setRequestProperty("accept", "application/json;charset=utf-8");
                        }
                );
            } catch (Exception e) {
                e.printStackTrace();
            }
            logger.warn("发送下游回调" + jsonData + "回调下游接口返回结果为：" + responseData);
            responseData = responseData == null ? "" : responseData;


            if (!("ok".equals(responseData.trim()))) {
                restCount++;
            } else {
                status = Constant.MERCHANT_CALL_STATUS_1;
                is = false;
            }

        } while(restCount <= 5 && is);

        entity.setStatus(status);

        try {
           merchantCallbakMapper.insert(entity);
        } catch (Exception e) {
            e.printStackTrace();
        }


        ResultDO result = orderService.getByMerchantSerialNumber(serialNumber);
        if (!result.isSuccess()) {
            return result;
        }
        OrderDO orderDO = (OrderDO) result.getModel(ResultDO.FIRST_MODEL_KEY);
        logger.debug("更新订单的回调状态信息" + orderDO + " orderId:" + orderDO.getId());
        orderDO.setMerchantCallbackInfo(responseData);
        orderDO.setMerchantCallbackStatus(status);
        orderService.saveUpdate(orderDO);
        result.setModel(ResultDO.FIRST_MODEL_KEY, orderDO);
        return result;
    }

    @Override
    public ResultDO getListByProviderId(String providerId) {

        ResultDO result = new ResultSupport();
        if(StringUtils.isEmpty(providerId)){
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PARAM_GET_ERROR);
            logger.debug("error code：" + ErrorCode.PARAM_GET_ERROR.getCode() + " msg" + ErrorCode.PARAM_GET_ERROR.getMsg());
            return result;
        }
        List<MerchantEntity> mList = baseMapper.selectList(Wrappers.<MerchantEntity>lambdaQuery().eq(MerchantEntity::getIsDelete, Constant.IS_DELETE_FALSE).eq(MerchantEntity::getStatus, Constant.MERCHANT_STATUS_1));
        if(mList == null || mList.isEmpty()){
            return result;
        }
        List<MerchantDO> doList = mList.stream().map( item -> getDomain(item)).collect(Collectors.toList());
        //根据供应商ID查询路由  白名单排除
        result =  routeFilterService.findRouterByProviderId(providerId,Constant.ROUTER_FILTER_TYPE_2);
        if(!result.isSuccess()){
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        RouteFilterDO routeFilterDO = (RouteFilterDO) result.getModel(ResultDO.FIRST_MODEL_KEY);
        if(routeFilterDO != null){
            List<String> whiteList = routeFilterDO.getMerchantIds();
            if(whiteList != null && !whiteList.isEmpty()){
                doList = doList.stream().filter(item -> !whiteList.contains(item.getId())).collect(Collectors.toList());
            }
        }
        //根据供应商ID查询路由  黑名单排除
        result = routeFilterService.findRouterByProviderId(providerId,Constant.ROUTER_FILTER_TYPE_1);
        if(!result.isSuccess()){
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        routeFilterDO = (RouteFilterDO) result.getModel(ResultDO.FIRST_MODEL_KEY);

        if(routeFilterDO != null){
            List<String> blackList = routeFilterDO.getMerchantIds();
            if(blackList != null && !blackList.isEmpty()){
                doList = doList.stream().filter(item -> !blackList.contains(item.getId())).collect(Collectors.toList());
            }
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }

    @Override
    public ResultDO getMerchantInfo(String id) {
        ResultDO result = new ResultSupport();
        StringBuffer sb = new StringBuffer();
        result = this.get(id);
        if(!result.isSuccess()){
            sb.append("获取商户开户信息失败");
            result.setModel(ResultDO.FIRST_MODEL_KEY, sb.toString());
            return result;
        }
        MerchantDO merchant = (MerchantDO) result.getModel(ResultDO.FIRST_MODEL_KEY);
        if(merchant != null){

            result = userService.getByMerchantId(id);
            if(result.isSuccess()){
                UserLoginDO user = (UserLoginDO) result.getModel(ResultDO.FIRST_MODEL_KEY);
                if(user != null){
                    sb.append("登陆名：" + user.getUsername() + "\n");
                    sb.append("密码：" + userPassword + "\n");
                }
            }
            sb.append("商户号：" + merchant.getMerchantNo() + "\n");
            sb.append("秘钥：" + merchant.getPrivateKey() + "\n");
            sb.append("在线文档：http://" + hostIp + "/api.html\n");
            sb.append("下单地址: http://" + hostIp + contextPath + "/api/recharge.html\n");
            sb.append("余额查询地址: http://" + hostIp + contextPath + "/api/find_balance.html\n");
            sb.append("订单查询: http://" + hostIp + contextPath + "/api/find_order.html\n");
            sb.append("\n");
            result = goodsMerchantService.listByMerchantId(merchant.getId());
            if(result.isSuccess()){
                List<GoodsMerchantDO> list = (List<GoodsMerchantDO>) result.getModel(ResultDO.FIRST_MODEL_KEY);
                if(list != null && list.size() >0){
                    List<GoodsDO> goodsList = new ArrayList<>();
                    for (GoodsMerchantDO obj : list) {
                        result = goodsService.get(obj.getGoodsId());
                        if(result.isSuccess()){
                            GoodsDO goods = (GoodsDO) result.getModel(ResultDO.FIRST_MODEL_KEY);
                            goodsList.add(goods);
                        }
                    }
                    if(goodsList != null && goodsList.size() >0){
                        List<GoodsDO> sortGoodsList = goodsList.stream().sorted(Comparator.comparing(GoodsDO::getServiceProvider).thenComparing(GoodsDO::getDenomination)).collect(Collectors.toList());
                        int index = 0;
                        int serviceProvider = 0;
                        for (GoodsDO goods : sortGoodsList) {
                            if(serviceProvider == 0){
                                serviceProvider = goods.getServiceProvider();
                            }
                            if(serviceProvider != goods.getServiceProvider()){
                                sb.append("\n");
                                serviceProvider = goods.getServiceProvider();
                            }
                            sb.append(goods.getGoodsNo() + "    " + goods.getTitle() + "\n");
                        }
                    }
                }
            }
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, sb.toString());
        return result;
    }


    private MerchantDO getDomain(MerchantEntity entity) {

        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        MerchantDO domain = new MerchantDO();

        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }

    private List<MerchantDO> getDomainList(List<MerchantEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<MerchantDO> doList = new ArrayList<MerchantDO>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(MerchantEntity entity : list) {

                MerchantDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }
}
